package com.campus.runrun.common.shiro;

import com.alibaba.fastjson.JSON;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.campus.runrun.model.dto.UserJwtDTO;
import com.campus.runrun.model.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Slf4j
@Component
public class JWTUtil {

    // 过期时间15天
    public static final long EXPIRE_TIME = 60 * 60 * 1000 * 24 * 15;
    public static final String TOKEN_SECRET = "123456";

    /**
     * token名
     */
    public static final String TOKEN_HEADER = "Authorization";


    /**
     * @param userJwtDTO
     * @return
     */
    public static String createTokenByWxAccount(UserJwtDTO userJwtDTO) {

        String jwtId = "runrun_user_token:" + Integer.toString(userJwtDTO.getId());
        Date date = new Date(System.currentTimeMillis() + EXPIRE_TIME);
        Algorithm algorithm = null;
        try {
            algorithm = Algorithm.HMAC256(TOKEN_SECRET);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        // 附带user信息
        String token = JWT.create()
                .withClaim("userId", userJwtDTO.getId())
                .withClaim("openId", userJwtDTO.getOpenId())
                .withClaim("username", userJwtDTO.getUsername())
                .withClaim("jwt-id", jwtId)
                .withExpiresAt(date)
                .sign(algorithm);

        // redis缓存JWT,并设置过期时间
       // redisTemplate.opsForValue().set("JWT-SESSION-" + jwtId, token, EXPIRE_TIME, TimeUnit.SECONDS);
        return token;
    }


    /**
     * JWT、token续期
     */
    public static void acceptExpiresAt(String token) {
        // 获取算法相同的JWTVerifier
        Algorithm algorithm = null;
        try {
            algorithm = Algorithm.HMAC256(TOKEN_SECRET);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        JWTVerifier verifier = JWT.require(algorithm)
                .withClaim("userId",getUserId(token))
                .withClaim("openId", getOpenId(token))
                .withClaim("username", getUsername(token))
                .withClaim("jwt-id", getJwtIdByToken(token))
                // JWT续期
                .acceptExpiresAt(System.currentTimeMillis() + EXPIRE_TIME)
                .build();

    }


    /**
     * @return token中包含的openId
     */
    public static String getOpenId(String token) throws JWTDecodeException {
        return JWT.decode(token).getClaim("openId").asString();
    }

    /**
     * 根据token获取stuId
     */
    public static Integer getUserId(String token) throws JWTDecodeException {
        return JWT.decode(token).getClaim("userId").asInt();
    }

    /**
     * 根据token获取学生名
     */
    public static String getUsername(String token) throws JWTDecodeException {
        return JWT.decode(token).getClaim("username").asString();
    }



    /**
     * 根据token获取jwt-id
     */
    public static String getJwtIdByToken(String token) throws JWTDecodeException {
        return JWT.decode(token).getClaim("jwt-id").asString();
    }


    public static UserVO getUserInfoByToken(String token) throws JWTDecodeException {
        UserVO userVO = new UserVO();
        userVO.setId(JWTUtil.getUserId(token));
        userVO.setUsername(JWTUtil.getUsername(token));
        userVO.setToken(token);
        return userVO;
    }

    /**
     * 校验token是否正确
     *
     * @param token  密钥
     * @return 是否正确
     */
    public static boolean verifyToken(String token) {

        DecodedJWT decodedJWT;
        Algorithm algorithm = null;
        try {
            algorithm = Algorithm.HMAC256(TOKEN_SECRET);
        } catch (UnsupportedEncodingException e) {
            log.info("token令牌不合法");
            e.printStackTrace();
        }
        JWTVerifier jwtVerifier = JWT.require(algorithm)
                 .acceptExpiresAt(System.currentTimeMillis() + EXPIRE_TIME)
                 .build();
        try {
            decodedJWT = jwtVerifier.verify(token);
        } catch (JWTVerificationException e) {
            log.info("token令牌不合法");
            return false;
        }

        // 续期令牌，延长令牌的有效性
        acceptExpiresAt(token);
        return true;
    }

}